<?php
/*
Plugin Name: WS Table Of Contents
Plugin URI: http://icyleaf.com/projects/ws-toc/
Description: WS TOC allows you to easily create a table of contents through HTML headings from Post/Page. 
Version: 0.6.2
Author: icyleaf
Author URI: http://icyleaf.com

Copyright 2008 icyleaf  (email: icyleaf.cm@gmail.com)

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/

//i18n
load_plugin_textdomain('ws-toc', $path = 'wp-content/plugins/ws-toc');

// define URL
$myabspath = str_replace('\\','/',ABSPATH);  // required for Windows & XAMPP
define('WINABSPATH', $myabspath);
define('WSTOCFOLDER', dirname(plugin_basename(__FILE__)));
define('WSTOC_ABSPATH', $myabspath.'wp-content/plugins/' . WSTOCFOLDER .'/');
define('WSTOC_URLPATH', get_option('siteurl').'/wp-content/plugins/' . WSTOCFOLDER.'/');

/**
 * Plugin init
 */
function WSTOC_init()
{
	add_filter('the_content', 'WSTOC_create');
	//add_action('admin_menu', 'WSTOC_add_options_page');
	add_action('wp_head', 'WSTOC_head');
}
add_action('init', 'WSTOC_init');

/**
 * Create Table of Contents
 *
 * @param (string) $content
 * @return (string) $ontent
 */
function WSTOC_create($content)
{
	// Check if enable to show contents
	$valid = strpos($content, '[toc');
	if ( empty($valid) )
	{
		return $content;
	}
	else
	{
		$start_key = '<h1>';
		$end_key = '</h1>';
		$step = 0;

		// Matching expression, then return results
		$content = preg_replace_callback( '/\[(toc|toc (([^]]+)))]/i', 'WSTOC_matching', $content);
		
		// Search for tags inside the post
		if ( is_int(strpos($content, $start_key, $step)) )
		{
			$vai = true;
			$results_i = array(); // start offset
			$results_f = array(); // end offset
			$results_t = array(); // name of <h1> labels
			
			// Fetch out the begining offset, the end offset and the name of <h1> labels
			while ( $vai )  {
				$r = strpos($content, $start_key, $step);
				if ( is_int($r) ){
					array_push($results_i, $r);
					$step=$r+1;
					$f = strpos($content, $end_key, $step);
					if ( $f ){
						array_push($results_f, $f);
						array_push($results_t,substr($content, $r+4, $f-($r+4)));
					}
				} else $vai = false;
			};
			
			// If there is text before the first tab, print it
			If ($results_i[0] > 0) $new_content .= substr($content, 0, $results_i[0]);
			
			$menu = '<ol>';

			// print new content
            $end = FALSE;
			for ( $i=0; $i<sizeof($results_t); $i++ )
			{
                if (sizeof($results_t)-$i==1)
					$temp_content = substr($content, $results_f[$i]+5);
				else
					$temp_content = substr($content, $results_f[$i]+5, $results_i[$i+1]-$results_f[$i]-5);
                    
                if ( $end )
                {
                    $new_content .= $start_key.$results_t[$i].$end_key.$content_11;
                    continue;
                }
                else
                {
                    $slug =  WSTOC_format($results_t[$i]);
                    // Add contents from <h1> labels
                    $menu .= '<li><a href="#'.$slug.'">' . $results_t[$i] . '</a></li>';

                    if ( !is_feed() && preg_match('/rel="top"/', $content) )
                        $new_content .='<div class="wstoc_section">
                            <hr class="wstoc_separator"/>
                            <span class="wstoc_top"><a href="#main">'.__('Top', 'ws-toc').'</a></span>
                            </div>';

                    // Add unique id to <h1> labels
                    $new_content .= '<h1 id='.$slug.' class="wstoc_caption">'.$results_t[$i].'</h1>';
                    if ( preg_match('/\[\/toc\]/', $temp_content) )
                    {
                        $end = TRUE;
                        $new_content .= preg_replace('/\[\/toc\]/', '', $temp_content);
                    }
                    else
	            	{
	            		$new_content .= $temp_content;
	            	}
                }
			}
			$menu .= '</ol>';
			
			return preg_replace('/\[ws-toc\]/', $menu, '<a name="main"></a>'.$new_content);
		} else return $content;
	}
}

/**
 * Matching expression
 *
 * @param (string) $matches
 * @return (string) $output
 */
function WSTOC_matching($matches)
{
	// Split options
	$split = preg_split("/[\|]/", $matches[2]);
	$attr = array();
	foreach ( explode(' ', $split[0]) as $str )
	{
		if ( preg_match('/(\s+)/', $str) || empty($str) ) continue;
		array_push($attr, $str);
	}	
	
	if ( sizeof($attr)>0 )
	{
		$content_ol = '<div id="wstoc_style"';
		foreach( $attr as $item )
		{
			$result = preg_split('/=/', $item);
			$result[1] = preg_replace('/"/','',$result[1]);

			if ( $result[0]=='display' )
			{
				$content_display = '<span id="wstoc_display">[<a id="wstoc_toggle" href="javascript:toggleTOC();">';
				if ( $result[1]=='hide' )
				{
					$content_display .= __('show', 'ws-toc');
					$content_ol .= ' style="display:none"';
				}
				else $content_display .= __('hide', 'ws-toc');
				$content_display .= '</a>]</span>';
			}
			else if ( $result[0]=='style' )
			{
				if ( $result[1]=='roman' )
					$content_ol .= ' class="wstoc_style_roman"';
				else if ( $result[1]=='alpha' )
					$content_ol .= ' class="wstoc_style_alpha"';
				else // $result[1]=='decimal' or other
					$content_ol .= ' class="wstoc_style_decimal"';
			}
			else if ( $result[0]=='top' )
			{
				$rel = ' rel="top"';
			}
		}
		$content_ol .= '>[ws-toc]</div>';
		
		$output = '<div id="wstoc_wrap">
			<h2 id="wstoc_title"'.$rel.'>'.__('Table of Contents', 'ws-toc').'</h2>';
		if ( !is_feed() ) 
			$output .= $content_display;
		$output .= $content_ol.'</div>';
		return $output;
	} else return '<div id="wstoc_wrap">'.
			'<span id="wstoc_title">'.__('Table of Contents', 'ws-toc').'</span>'.
			'<div id="wstoc_style">[ws-toc]</div></div>';
}

/**
 * Formaet String
 * @param (string) $string
 * @return (string) $string
 */
function WSTOC_format($string)
{
	if ( preg_match('/['.chr(0xa1).'-'.chr(0xff).']+/', $string) )
	{
		return preg_replace('/\s+/','-',$string);
	}
	else
	{
		// process of non-Chinese string
		$string = preg_replace("`\[.*\]`U","",$string);
		$string = preg_replace('`&(amp;)?#?[a-z0-9]+;`i','-',$string);
		$string = htmlentities($string, ENT_COMPAT, 'utf-8');
		$string = preg_replace("`&([a-z])(acute|uml|circ|grave|ring|cedil|slash|tilde|caron|lig|quot|rsquo);`i","\\1", $string);
		$string = preg_replace(array("`[^a-z0-9]`i","`[-]+`") , "-", $string);
		return strtolower(trim($string, '-'));
	}
}

/**
 * Add CSS and JS codes to <head> section
 */
function WSTOC_head()
{
	echo "\n".'<!--[WS TOC v0.6]-->'."\n";
	echo '<link type="text/css" rel="stylesheet" href="'.WSTOC_URLPATH.'ws-toc.css" />'."\n";
	echo '<script type="text/javascript">
		function toggleTOC(){
			if ( document.getElementById("wstoc_toggle").innerHTML=="hide" ) {
				document.getElementById("wstoc_toggle").innerHTML = "show";
				document.getElementById("wstoc_style").style.display = "none";
			} else {
				document.getElementById("wstoc_toggle").innerHTML = "hide";
				document.getElementById("wstoc_style").style.display = "block";
			}
		}
		</script>';
	echo "\n".'<!--[/WS TOC]-->'."\n";
}

/**
 * Add plugin page to admin
 */
function WSTOC_add_options_page()
{
	if ( function_exists('add_options_page') ) {
		add_options_page(__('WS TOC'), __('WS TOC'), 8, basename(__FILE__), 'WSTOC_config_page');
	}
}

/**
 * Config page
 */
function WSTOC_config_page()
{
	echo 'WS TOC Configures';
}
?>
